#pragma once

#include <map>
using std::map;

template <typename ClassIDType, typename BaseClassType>
class ObjectGenerator
{
private:
	typedef BaseClassType* (*ObjectCreator)();
	map<ClassIDType, ObjectCreator> m_ObjectCreators;
	static ObjectGenerator<ClassIDType, BaseClassType> sm_Instance;
	ObjectGenerator() {}
	ObjectGenerator(const ObjectGenerator&);
	ObjectGenerator& operator=(const ObjectGenerator&);
	~ObjectGenerator(void) {}
	template<typename DerivedClassType>
	static BaseClassType* ConstructObject()
	{
		return new DerivedClassType;
	}

public:
	static ObjectGenerator<ClassIDType, BaseClassType>* GetInstance()
	{
		return &sm_Instance;
	}
	template<typename DerivedClassType>
	bool RegisterClassType(ClassIDType id)
	{
		std::pair<ClassIDType, ObjectCreator> objTypeDef;
		objTypeDef.first	=	id;
		objTypeDef.second	=	ConstructObject<DerivedClassType>;
		m_ObjectCreators.insert(objTypeDef);
		return true;
	}
	bool UnregisterClassType(ClassIDType id)
	{
		map<ClassIDType, ObjectCreator>::iterator iter = m_ObjectCreators.find(id);
		if (iter == m_ObjectCreators.end())
			return false;
		m_ObjectCreators.erase(iter);
		return true;
	}
	BaseClassType* MakeObject(ClassIDType id)
	{
		map<ClassIDType, ObjectCreator>::iterator iter = m_ObjectCreators.find(id);
		if (iter == m_ObjectCreators.end())
			return NULL;
		return (*iter).second();
	}
	void ShutdownObjectFactory()
	{
		m_ObjectCreators.clear();
	}
}; 
template<typename ClassIDType, typename BaseClassType>
ObjectGenerator<ClassIDType, BaseClassType> 
ObjectGenerator<ClassIDType, BaseClassType>::sm_Instance;


